﻿

Namespace YahooManaged.Finance.API


    Public Class CompanyProfileDownload
        Inherits Base.Download

        Friend mFinanceHelper As New FinanceHelper

        Public Event AsyncDownloadCompleted(ByVal sender As Base.Download, ByVal e As CompanyProfileDownloadCompletedEventArgs)

        Public Function Download(ByVal managedID As IID) As CompanyProfileResponse
            If managedID Is Nothing Then Throw New ArgumentNullException("managedID", "The ID object is null")
            Return Me.Download(managedID.ID)
        End Function
        Public Function Download(ByVal unmanagedID As String) As CompanyProfileResponse
            If unmanagedID.Trim = String.Empty Then Throw New ArgumentException("The ID is empty", "unmanagedID")
            Return Me.ToResponse(MyBase.DownloadStream(Me.DownloadURL(unmanagedID)), unmanagedID.ToUpper)
        End Function

        Public Sub DownloadAsync(ByVal managedID As IID, Optional ByVal userArgs As Object = Nothing)
            If managedID Is Nothing Then Throw New ArgumentNullException("managedID", "The ID object is null")
            Me.DownloadAsync(managedID.ID, userArgs)
        End Sub
        Public Sub DownloadAsync(ByVal unmanagedID As String, Optional ByVal userArgs As Object = Nothing)
            If unmanagedID.Trim = String.Empty Then Throw New ArgumentException("The ID is empty", "unmanagedID")
            Dim args As New AsyncArgs(userArgs, unmanagedID.ToUpper)
            MyBase.DownloadStreamAsync(Me.DownloadURL(args.ID), args)
        End Sub


        Private Sub AsyncDownload_Completed(ByVal sender As Base.Download, ByVal e As Base.StreamDownloadCompletedEventArgs) Handles MyBase.AsyncStreamDownloadCompleted
            Dim args = CType(e.UserArgs, AsyncArgs)
            RaiseEvent AsyncDownloadCompleted(Me, New CompanyProfileDownloadCompletedEventArgs(args.UserArgs, Me.ToResponse(e.Response, args.ID)))
        End Sub

        Private Function DownloadURL(ByVal id As String) As String
            Dim whereClause As String = String.Format("url=""http://finance.yahoo.com/q/pr?s={0}"" AND xpath='//table[@id=""yfncsumtab""]/tr/td/table'", mHelper.CleanYqlParam(mFinanceHelper.CleanIndexID(id)))
            Dim url = mHelper.YqlUrl("*", "html", whereClause, Nothing, False)
            Return url
        End Function

        Private Function ToResponse(ByVal resp As Base.StreamResponse, ByVal id As String) As CompanyProfileResponse
            Dim res As CompanyProfileData = Nothing
            Dim convCulture As New Globalization.CultureInfo("en-US")
            Dim resultsNodes = mHelper.GetResultsFromXml(resp.Result, "results")
            If resultsNodes.Length > 0 Then
                Dim hasValues As Boolean = False
                res = New CompanyProfileData
                res.SetID(mFinanceHelper.CleanIndexID(id))
                Dim resultNode = resultsNodes(0)

                Dim nameNode = resultNode.SelectSingleNode("//table/tr/td[1]/strong")
                If nameNode IsNot Nothing Then
                    res.CompanyName = nameNode.InnerText
                    hasValues = True
                End If

                Dim addressNode = resultNode.SelectSingleNode("//table/tr/td[1]/p")
                If addressNode IsNot Nothing Then
                    Dim rawAddress = addressNode.InnerText.Split(New String() {vbLf}, StringSplitOptions.RemoveEmptyEntries)
                    Dim formattedAddress As New Text.StringBuilder
                    For Each line In rawAddress
                        If Not line.Contains("Website") Then
                            Dim l = line.Trim.Replace("MapPhone", "Phone")
                            If l.EndsWith(" -") Then
                                l = l.Replace(" -", "")
                            End If
                            formattedAddress.AppendLine(l)
                        Else
                            Exit For
                        End If
                    Next
                    res.Address = formattedAddress.ToString.TrimEnd
                    hasValues = Not res.Address.Contains("is no Profile data available for ")
                End If

                Dim indicesNode = resultNode.SelectSingleNode("//table/tr/td[1]/table[2]/tr/td/table/tr/td[2]")
                If indicesNode IsNot Nothing Then
                    Dim lstIndices As New List(Of KeyValuePair(Of String, String))
                    For Each indexLink As XmlNode In indicesNode.ChildNodes
                        If indexLink.Name = "a" Then
                            Dim indexID As String = Uri.UnescapeDataString(indexLink.Attributes("href").InnerText.Replace("http://finance.yahoo.com/q?s=", "").Replace("&d=t", ""))
                            Dim name As String = String.Empty
                            For Each p In indexLink.InnerText.Split(New String() {vbLf}, StringSplitOptions.None)
                                name &= p.Trim & " "
                            Next
                            lstIndices.Add(New KeyValuePair(Of String, String)(indexID, name.TrimEnd))
                        End If
                    Next
                    res.Details.IndexMembership = lstIndices.ToArray
                    hasValues = True
                End If

                Dim sectorsNode = resultNode.SelectSingleNode("//table/tr/td[1]/table[2]/tr/td/table/tr[2]/td[2]")
                If sectorsNode IsNot Nothing Then
                    For Each sectorLink As XmlNode In sectorsNode.ChildNodes
                        If sectorLink.Name = "a" Then
                            For Each sect As Sector In [Enum].GetValues(GetType(Sector))
                                Dim name As String = String.Empty
                                For Each p In sectorLink.InnerText.Split(New String() {vbLf}, StringSplitOptions.None)
                                    name &= p.Trim & " "
                                Next
                                name = name.TrimEnd
                                If sect.ToString.Replace("_", " ") = name Then
                                    res.Details.Sector = sect
                                    Exit For
                                End If
                            Next
                        End If
                    Next
                    hasValues = res.Details.Sector IsNot Nothing
                End If

                Dim industryNode = resultNode.SelectSingleNode("//table/tr/td[1]/table[2]/tr/td/table/tr[3]/td[2]")
                If industryNode IsNot Nothing Then
                    For Each industryLink As XmlNode In industryNode.ChildNodes
                        If industryLink.Name = "a" Then
                            Dim indIndex As Integer = 0
                            If Integer.TryParse(industryLink.Attributes("href").InnerText.Replace("http://biz.yahoo.com/ic/", "").Replace(".html", ""), indIndex) Then
                                res.Details.Industry = CType(indIndex, Industry)
                            End If
                        End If
                    Next
                    hasValues = res.Details.Industry IsNot Nothing
                End If

                Dim employeesNode = resultNode.SelectSingleNode("//table/tr/td[1]/table[2]/tr/td/table/tr[4]/td[2]")
                If employeesNode IsNot Nothing Then
                    If Integer.TryParse(employeesNode.InnerText.Trim, Globalization.NumberStyles.Any, convCulture, res.Details.FullTimeEmployees) Then
                        hasValues = True
                    End If
                End If

                Dim summaryNode = resultNode.SelectSingleNode("//table/tr/td[1]/p[2]")
                If summaryNode IsNot Nothing Then
                    Dim summaryText As New Text.StringBuilder
                    For Each line In summaryNode.InnerText.Split(New String() {vbLf}, StringSplitOptions.None)
                        summaryText.Append(line.Trim & " ")
                    Next
                    res.BusinessSummary = summaryText.ToString.TrimEnd
                    hasValues = True
                End If

                Dim websitesNodes = resultNode.SelectSingleNode("//table/tr/td[1]/table[5]/tr/td")
                If websitesNodes IsNot Nothing Then
                    Dim lstWebsites As New List(Of Uri)
                    For Each linkNode As XmlNode In websitesNodes.ChildNodes
                        If linkNode.Name = "a" Then
                            lstWebsites.Add(New Uri(linkNode.Attributes("href").InnerText))
                        End If
                    Next
                    res.CompanyWebsites = lstWebsites.ToArray
                    hasValues = True
                End If

                Dim governanceNode = resultNode.SelectSingleNode("//table/tr/td[3]/table[2]/tr/td/p")
                If governanceNode IsNot Nothing Then
                    Dim governanceText As New Text.StringBuilder
                    For Each line In governanceNode.InnerText.Split(New String() {vbLf}, StringSplitOptions.None)
                        governanceText.Append(line.Trim & " ")
                    Next
                    res.CorporateGovernance = governanceText.ToString.TrimEnd
                    hasValues = True
                End If



                Dim executivesNode As XmlNode
                Dim executivesHeader = resultNode.SelectSingleNode("//table/tr/td[3]/table[3]/tr/th/span")
                If executivesHeader IsNot Nothing AndAlso executivesHeader.InnerText.Contains("Executives") Then
                    executivesNode = resultNode.SelectSingleNode("//table/tr/td[3]/table[4]/tr/td/table")
                Else
                    executivesNode = resultNode.SelectSingleNode("//table/tr/td[3]/table[2]/tr/td/table")
                End If
                If executivesNode IsNot Nothing Then


                    Dim lst As New List(Of ExecutivePersonInfo)
                    Dim isFirst As Boolean = True
                    For Each row As XmlNode In executivesNode.ChildNodes
                        If Not isFirst Then
                            If row.Name = "tr" Then
                                If row.ChildNodes.Count >= 3 Then
                                    Dim exec As New ExecutivePersonInfo

                                    Dim name As String = String.Empty
                                    For Each l In row.ChildNodes(0).FirstChild.InnerText.Split(New String() {vbLf}, StringSplitOptions.None)
                                        name &= l.Trim & " "
                                    Next
                                    exec.Name = name.TrimEnd

                                    Dim position As String = String.Empty
                                    For Each l In row.ChildNodes(0).LastChild.InnerText.Split(New String() {vbLf}, StringSplitOptions.None)
                                        position &= l.Trim & " "
                                    Next
                                    Integer.TryParse(position.Substring(2, 2), exec.Age)
                                    exec.Position = position.Substring(4).Trim


                                    Dim payStr = row.ChildNodes(1).FirstChild.InnerText.Replace(vbLf, "").Trim
                                    If Not payStr.Contains("N/A") Then
                                        Double.TryParse(payStr, Globalization.NumberStyles.Any, convCulture, exec.Pay)
                                    End If

                                    Dim executive = row.ChildNodes(2).FirstChild.InnerText.Replace(vbLf, "").Trim
                                    If Not payStr.Contains("N/A") Then
                                        Integer.TryParse(payStr, Globalization.NumberStyles.Any, convCulture, exec.Exercised)
                                    End If

                                    lst.Add(exec)
                                End If
                            End If
                        Else
                            isFirst = False
                        End If
                    Next
                    res.KeyExecutives = lst.ToArray
                    hasValues = True
                End If
                If Not hasValues Then res = Nothing
            End If


            Return New CompanyProfileResponse(resp.Connection, res)
        End Function

        Private Class AsyncArgs
            Inherits Base.DownloadEventArgs
            Public ID As String
            Public Sub New(ByVal userArgs As Object, ByVal id As String)
                MyBase.New(userArgs)
                Me.ID = id
            End Sub
        End Class

    End Class


    Public Class CompanyProfileResponse
        Inherits Base.Response

        Public Overloads ReadOnly Property Result As CompanyProfileData
            Get
                Return CType(MyBase.Result, CompanyProfileData)
            End Get
        End Property

        Friend Sub New(ByVal conn As Base.ConnectionInfo, ByVal result As CompanyProfileData)
            MyBase.New(conn, result)
        End Sub
    End Class

    Public Class CompanyProfileDownloadCompletedEventArgs
        Inherits Base.DownloadCompletedEventArgs

        Public Overloads ReadOnly Property Response As CompanyProfileResponse
            Get
                Return CType(MyBase.Response, CompanyProfileResponse)
            End Get
        End Property

        Friend Sub New(ByVal userArgs As Object, ByVal resp As CompanyProfileResponse)
            MyBase.New(userArgs, resp)
        End Sub

    End Class

End Namespace